package org.dromara.common.websocket.handler;

import lombok.extern.slf4j.Slf4j;
import org.dromara.common.websocket.domain.BoardWebSocketMessage;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
import org.dromara.common.websocket.enums.MessageType;
import org.dromara.common.websocket.event.BoardWebSocketMessageEvent;
import org.dromara.common.websocket.holder.WebSocketSessionHolder;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;

import java.util.Collections;

import static org.dromara.common.websocket.constant.WebSocketConstants.BOARD_CLIENT_KEY;

/**
 * WebSocketHandler 实现类
 *
 * @author zendwang
 */
@Slf4j
public class BoardWebSocketHandler extends AbstractWebSocketHandler {
    private final ApplicationEventPublisher applicationEventPublisher;

    public BoardWebSocketHandler(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    /**
     * 连接成功后
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        BoardWebSocketMessage webSocketMessage = (BoardWebSocketMessage) session.getAttributes().get(BOARD_CLIENT_KEY);
        WebSocketSessionHolder.addSession(webSocketMessage.getBoardId(), session);
        //设备上线
        webSocketMessage.setMessageType(MessageType.ONLINE);
        BoardWebSocketMessageEvent boardWebSocketMessageEvent = new BoardWebSocketMessageEvent(webSocketMessage, applicationEventPublisher);
        applicationEventPublisher.publishEvent(boardWebSocketMessageEvent);
        log.info("[connect] sessionId: {},板子id:{},板子ip:{}", session.getId(), webSocketMessage.getBoardId(), webSocketMessage.getBoardIp());
    }

    /**
     * 处理发送来的文本消息
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        BoardWebSocketMessage webSocketMessage = (BoardWebSocketMessage) session.getAttributes().get(BOARD_CLIENT_KEY);
        webSocketMessage.setMessageType(MessageType.MESSAGE);
        webSocketMessage.setMessage(message.getPayload());
//        BoardWebSocketMessageEvent boardWebSocketMessageEvent = new BoardWebSocketMessageEvent(webSocketMessage, applicationEventPublisher);
//        applicationEventPublisher.publishEvent(boardWebSocketMessageEvent);
        WebSocketMessageDto webSocketMessageDto = new WebSocketMessageDto();
        webSocketMessageDto.setSessionKeys(Collections.singletonList(webSocketMessage.getBoardId()));
        webSocketMessageDto.setMessage(message.getPayload());
        WebSocketUtils.publishMessage(webSocketMessageDto);
    }

    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception {
        super.handleBinaryMessage(session, message);
    }

    /**
     * 心跳监测的回复
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    protected void handlePongMessage(WebSocketSession session, PongMessage message) throws Exception {
        WebSocketUtils.sendPongMessage(session);
    }

    /**
     * 连接出错时
     *
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("[transport error] sessionId: {} , exception:{}", session.getId(), exception.getMessage());
    }

    /**
     * 连接关闭后
     *
     * @param session
     * @param status
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        BoardWebSocketMessage webSocketMessage = (BoardWebSocketMessage) session.getAttributes().get(BOARD_CLIENT_KEY);
        WebSocketSessionHolder.removeSession(webSocketMessage.getBoardId(), session.getId());
        //设备上线
        webSocketMessage.setMessageType(MessageType.OFFLINE);
        BoardWebSocketMessageEvent boardWebSocketMessageEvent = new BoardWebSocketMessageEvent(webSocketMessage, applicationEventPublisher);
        applicationEventPublisher.publishEvent(boardWebSocketMessageEvent);
        log.info("[disconnect] sessionId: {},板子id:{},板子ip:{}", session.getId(), webSocketMessage.getBoardId(), webSocketMessage.getBoardIp());
    }

    /**
     * 是否支持分片消息
     *
     * @return
     */
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

}
